package com.shiguiwu.springmybatis.javabase.annontation;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.TypeVariable;

/**
 * @description: 注解
 * @author: stone
 * @date: Created by 2021/3/12 9:14
 * @version: 1.0.0
 * @pakeage: com.shiguiwu.springmybatis.annontation
 */
public class AnnontationTests {


    //定义无参注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Ann1 {

    }

    @Ann1
    public static class UseAnn1 {

    }

    //有参注解
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Ann2 {
        String name() default "";

    }

    @Ann2(name = "hahaha")
    public static class UseAnn2 {

    }

    //一个参数为value的注解，可以省略参数名称
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Ann3 {

        String value() default "xxx";

    }

    @Ann3("shiguiwu")
    public static class UseAnn3 {

    }

    //数组类型参数
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Ann4 {
        String[] names() default {};
    }

    //todo 如果是一个参数，可以省略大括号
    @Ann4(names = {"shiguiwu", "zhoudongxiu"})
    public static class UseAnn4 {

    }

    //指定多个值
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Ann5 {

        String[] names() default {"shiguiwu", "小花"};

        //todo 一个值的时候，可以去掉 {}
        int[] score() default 1;

        int age() default 18;

        //不指定默认值
        String address();


    }

    //没有默认值，不写会报错 address
    @Ann5(names = {"一般", "牛逼"}, score = 2, age = 4, address = "湖南永州")
    public static class UseAnn5 {

    }

    //todo 综合案例
    @Target(value = {
            ElementType.TYPE
            , ElementType.METHOD
            , ElementType.CONSTRUCTOR
            , ElementType.FIELD
            , ElementType.LOCAL_VARIABLE
            , ElementType.PARAMETER
            //java8 新增 泛型上
            ,ElementType.TYPE_PARAMETER

    })
    @Retention(RetentionPolicy.RUNTIME)
    @interface Ann6 {
        String value();

        ElementType type();
    }

    @Ann6(value = "类上",type = ElementType.TYPE)
    public static class UseAnnPlus<@Ann6(value = "泛型上",type = ElementType.TYPE_PARAMETER)T> {

        @Ann6(value = "字段上",type = ElementType.FIELD)
        private String name;

        @Ann6(value = "构造器上",type = ElementType.CONSTRUCTOR)
        public UseAnnPlus() {

        }


        @Ann6(value = "方法上",type = ElementType.METHOD)
        public String getName() {
            return name;
        }

        public void setName(@Ann6(value = "参数上",type = ElementType.PARAMETER) String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            @Ann6(value = "本地变量上",type = ElementType.LOCAL_VARIABLE) String a = "aaa";
            return "UseAnnPlus{" +
                    "name='" + name + '\'' + a +
                    '}';
        }
    }

    //java8新增，可以用在任何位置
    @Target(ElementType.TYPE_USE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Ann7 {

        String value();

    }


    @Ann7("类上")
    public static class UseAnn {

        @Ann7("字段上")
        private String name;

        @Ann7("构造器")
        public UseAnn(@Ann7("参数上") String name) {
            @Ann7("临时变量") String temp = "";
            this.name = name;
        }

        //不能用在无返回值的方法上
        //@Ann7("方法上")
        //public void setName(String name) {
        //    this.name = name;
        //}

        @Ann7("方法上")
        public String getName() {
            return name;
        }


    }
    //注解继承 ,只限于父类，接口无法继承
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Inherited //具有继承性
    @interface Ann8 {
        String value();

    }
    @Ann8("接口中")
    public  interface IUseAnn8 {

    }

    public  interface IUseAnn8Impl extends IUseAnn8 {

    }

    @Ann8("继承类上")
    public static class UseAnn8 {


    }

    public static class UseAnn8Child extends UseAnn8 implements IUseAnn8{

    }








    public static void main(String[] args) throws NoSuchFieldException, NoSuchMethodException {
        //获取类型上的注解
        Annotation[] annotations = UseAnnPlus.class.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        System.out.println("=============================================================");
        //获取字段上的注解
        Field name = UseAnnPlus.class.getDeclaredField("name");
        Annotation[] annotations1 = name.getAnnotations();
        for (Annotation annotation : annotations1) {
            System.out.println(annotation.annotationType().isAssignableFrom(Ann6.class));
            System.out.println(annotation);
        }
        System.out.println("=============================================================");
        //获取构造器上的注解
        Constructor<?> constructor = UseAnnPlus.class.getConstructors()[0];
        Annotation[] annotations2 = constructor.getAnnotations();
        for (Annotation annotation : annotations2) {
            System.out.println(annotation);
        }

        System.out.println("=============================================================");
        //获取方法上的注解
        Method getName = UseAnnPlus.class.getMethod("getName");
        Annotation[] annotations3 = getName.getAnnotations();
        for (Annotation annotation : annotations3) {
            System.out.println(annotation);
        }
        System.out.println("=============================================================");

        //todo 解析类名后面的尖括号的部分，即下面的部分：
        TypeVariable<Class<UseAnnPlus>>[] typeParameters = UseAnnPlus.class.getTypeParameters();
        for (TypeVariable<Class<UseAnnPlus>> typeParameter : typeParameters) {
            System.out.println("变量类型的注解" + typeParameter.getName());
            Annotation[] annotations4 = typeParameter.getAnnotations();
            for (Annotation annotation : annotations4) {
                System.out.println(annotation);
            }
        }

        //获取参数注解
        System.out.println("=============================================================");
        Method setName = UseAnnPlus.class.getMethod("setName", String.class);
        Parameter[] parameters = setName.getParameters();
        for (Parameter parameter : parameters) {
            Annotation[] annotations4 = parameter.getAnnotations();
            for (Annotation annotation : annotations4) {
                System.out.println(annotation);
            }
        }

        System.out.println("=============================================================");
        //继承过来的注解

        Annotation[] annotations4 = UseAnn8Child.class.getAnnotations();
        Annotation[] annotations5 = IUseAnn8Impl.class.getAnnotations();
        for (Annotation annotation : annotations4) {
            System.out.println(annotation);
        }

        //todo 接口，不管是继承还是实现都没有用
        for (Annotation annotation : annotations5) {
            System.out.println(annotation);
        }
    }




}
